package de.koller.oceanFramework.tree;

import de.koller.oceanFramework.OceanException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

abstract public class Sea3A extends Sea3 {

	private boolean throwMother = true;
	
	@Override
	protected void init() {
		Class<?> my = this.getClass();
		handlClass( my );
		while( my != Object.class ) {
			my = my.getSuperclass();
			handlClass( my );
		}
	}

	private void handlClass( Class<?> c ) {
		Field[] fs = c.getDeclaredFields();
		for( Field f : fs ) {
			handleFieldMother( f );
			handleFieldChild( f );
		}
	}
	
	private void handleFieldChild( Field f ) {
		f.setAccessible( true );
		Child c = f.getAnnotation( Child.class );
		if( c == null )
			return;
		if( !Modifier.isFinal( f.getModifiers() ) )
			throw new OceanException( f.getName() + " muss final sein in " + this );
		
		try {
			ISea3 sea = (ISea3)f.get( this );
			this.addChild( sea );
		} catch ( Exception ex ) {
			throw new OceanException( ex );
		}
	}
	
	private void handleFieldMother( Field f ) {
		f.setAccessible( true );
		Mother m = f.getAnnotation( Mother.class );
		if( m == null )
			return;
		
		Class<?> t = f.getType();
		
		try {
			f.set( this, this.searchMother( (Class<? extends ISea3>)t ) );
		} catch( Exception ex ) {
			if( throwMother ) {
				throw new OceanException( "Can't find type: " + t + " as mother in "
						+ this );
			} else {
				try {
					//@todo schönere methode finden!
					f.set( this, null );
				} catch( Exception e ) {
					throw new OceanException( e );
				}
			}
		}
	}
	
	public final void dontThrowMotherException() {
		throwMother = false;
	}
	
}
